package com.lizi.apidoc.handler;

import com.lizi.apidoc.builder.ClassLoader;
import com.lizi.apidoc.constants.AnnotationKeyName;
import com.lizi.apidoc.constants.AnnotationName;
import com.lizi.apidoc.constants.DocGlobal;
import com.lizi.apidoc.model.ApiObjectProperty;
import com.lizi.apidoc.model.ApiReqHeader;
import com.lizi.apidoc.utils.*;
import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;
import com.thoughtworks.qdox.model.expression.AnnotationValue;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Request Param Handler
 *
 * @author kingman zhangjw@3vjia.com
 * @since 2020-05-07 12:40
 */
public class RequestParamHandler extends ParamHandler {


    public static RequestParamHandler builder() {
        return new RequestParamHandler();
    }

    public List<ApiObjectProperty> handle(final JavaMethod javaMethod, final String tagName) {
        String className = javaMethod.getDeclaringClass().getCanonicalName();
        Map<String, String> paramTagMap = DocUtil.getParamsComments(javaMethod, tagName, className);
        List<JavaParameter> parameterList = javaMethod.getParameters();
        if (ArraysUtil.isNullOrEmpty(parameterList)) {
            return null;
        }
        List<ApiObjectProperty> paramList = new ArrayList<>();
        for (JavaParameter parameter : parameterList) {
            String paramName = parameter.getName();
            String typeName = parameter.getType().getGenericCanonicalName();
            String simpleName = parameter.getType().getValue().toLowerCase();
            String fullTypeName = parameter.getType().getFullyQualifiedName();

            if (JavaClassValidateUtil.isMvcIgnoreParams(typeName)) {
                continue;
            }
            if (!paramTagMap.containsKey(paramName) && JavaClassValidateUtil.isPrimitive(fullTypeName)) {
                //这里可改为警告
                throw new RuntimeException("ERROR: Unable to find javadoc @param for actual param \""
                        + paramName + "\" in method " + javaMethod.getName() + " from " + className);
            }
            String comment = super.paramCommentResolve(paramTagMap.get(paramName));

            //region 文件上传
            if (typeName.contains(DocGlobal.MULTIPART_FILE_FULLY)) {
                ApiObjectProperty param = ApiObjectProperty.of().setName(paramName).setType("file")
                        .setFormat("file").setDescription(comment).setRequired(true).setVersion(DocGlobal.DEFAULT_VERSION);
                paramList.add(param);
                continue;
            }
            //endregion
            JavaClass javaClass = ClassLoader.getInstance().getJavaClassByFullTypeName(fullTypeName);
            List<JavaAnnotation> annotations = parameter.getAnnotations();
            String strRequired = "true";
            for (JavaAnnotation annotation : annotations) {
                String annotationName = JavaClassUtil.getAnnotationSimpleName(annotation.getType().getName());
                if (AnnotationName.REQUEST_HERDER.equals(annotationName)) {
                    continue;
                }

                if (AnnotationName.REQUEST_PARAM.equals(annotationName) ||
                        AnnotationName.SHORT_PATH_VARIABLE.equals(annotationName)) {
                    AnnotationValue annotationValue = annotation.getProperty(AnnotationKeyName.VALUE);
                    if (null != annotationValue) {
                        paramName = StringUtil.removeQuotes(annotationValue.toString());
                    }
                    AnnotationValue annotationOfName = annotation.getProperty(AnnotationKeyName.NAME);
                    if (null != annotationOfName) {
                        paramName = StringUtil.removeQuotes(annotationOfName.toString());
                    }
                    AnnotationValue annotationRequired = annotation.getProperty(AnnotationKeyName.REQUIRED);
                    if (null != annotationRequired) {
                        strRequired = annotationRequired.toString();
                    }
                }
            }
            Boolean required = Boolean.parseBoolean(strRequired);
            ApiObjectProperty supperGetParams = super.getApiParams(paramName,fullTypeName,simpleName,typeName,comment,required);
            if(supperGetParams!=null) {
                paramList.add(supperGetParams);
            }
        }
        return paramList;
    }

}
